#This file defines various convenience methods for filtering as well as some other handy functions
import re

CONVERSIONS = {"int":int,"float":float,"string":str,"number":int}

def QualificationMatches(page):
	return page.parseByName("Qualification Matches")

def EliminationMatches(page):
	return page.parseByName("Elimination Matches")

def QualificationSchedule(page):
	return page.parseByName("Qualification Schedule")

def EliminationSchedule(page):
	return page.parseByName("Elimination Schedule")

def TeamList(page):
	return page.parseByIndex(2,['Location','Name','Number'],3)

def Awards(page):
	return page.parseByIndex(2)

def Standings(page):
	return page.parseByIndex(2)

def safeConvert(val,toType):
	try:
		return toType(val)
	except:
		return None

#Generic helper methods, they take a list of functions. 
def filterByAll(filters):
	if filters:
		return lambda item: all(map(lambda function: function(item),filters))
	return lambda item: True

def filterByAny(filters):
	if filters: 
		return lambda item: any(map(lambda function: function(item),filters))
	return lambda item: True

def greaterThan(cell,convFunc,number):
	return lambda item: convFunc(item[re.sub("_"," ",cell)]) > number

def lessThan(cell,convFunc,number):
	return lambda item: convFunc(item[re.sub("_"," ",cell)]) < number

#Don't use this function with floats, equality for floats isn't assured
def equalTo(cell,convFunc,number):
	return lambda item: convFunc(item[re.sub("_"," ",cell)]) == number

def getByKey(el,key):
	return el[re.sub("_"," ",key)]

def sortByKeys(L,keys,asType = int, ascending = True):
	if keys:
		L.sort(key = lambda x: map(lambda key: safeConvert(getByKey(x,key),asType),keys), reverse = not ascending)
	return L

CONVERSIONS = {"int":int,"float":float,"string":str}
TYPES = {"OR":filterByAny,"AND":filterByAll,"":filterByAll}

def safeConvertArgs(val,toType):
	try:
		return CONVERSIONS[toType](val)
	except:
		return None

#Standings related stuff
def hasMoreWins(wins):
	return lambda match: int(match["Wins"]) > int(wins)

def hasLessWins(wins):
	return lambda match: int(match["Wins"]) < int(wins)

def hasLosses(Losses):
	return lambda match: int(match["Losses"]) == losses

def hasMoreLosses(Losses):
	return lambda match: int(match["Losses"]) > losses

def hasLessLosses(Losses):
	return lambda match: int(match["Losses"]) < losses

def hasLosses(Losses):
	return lambda match: int(match["Losses"]) == losses

def aboveRank(rank):
	return lambda match: int(match["Rank"]) > rank

def belowRank(rank):
	return lambda match: int(match["Rank"]) < rank

def isRank(rank):
	return lambda match: int(match["Rank"]) == rank

def aboveQS(qs):
	return lambda match: int(float(match["QS"])) > qs

def belowQS(qs):
	return lambda match: int(float(match["QS"])) < qs

def isQS(qs):
	return lambda match: int(float(match["QS"])) == qs

def aboveRS(rs):
	return lambda match: float(match["RS"]) >= rs

def belowRS(rs):
	return lambda match: float(match["RS"]) <= rs		

def aboveMP(mp):
	return lambda match: float(match["RS"]) > mp

def belowMP(mp):
	return lambda match: float(match["RS"]) < mp

def playedAtLeast(matches):
	return lambda match: int(match["Played"]) > matches

def playedAtMost(matches):
	return lambda match: int(match["Played"]) < matches

def playedMatches(matches):
	return lambda match: int(match["Played"]) == matches


# Team List related filters

def isTeam(number):
	return lambda team: int(team["Number"]) == number

#Match Related Stuff, works for schedule and result pages.
def redWins(match):
	return int(match['Red Score']) > int(match['Blue Score'])

def blueWins(match):
	return int(match['Red Score']) < int(match['Blue Score'])

def tie(match):
	return int(match['Red Score']) == int(match['Blue Score'])

def redAlliance(match):
	return (int(match['Red 1']),int(match['Red 2']),int(match['Red 3']))

def blueAlliance(match):
	return (int(match['Blue 1']),int(match['Blue 2']),int(match['Blue 3']))	

def teams(match):
	return redAlliance(match) + blueAlliance(match)	

def played(team):
	return (lambda match: int(team)in teams(match))

def isRed(team):
	return (lambda match: int(team)in redAlliance(match))

def isBlue(team):
	return (lambda match: int(team)in blueAlliance(match))

def completed(match):
	return (match['Red Score'] != '' and match['Blue Score'] != '')

def winningAlliance(match):
	if blueWins(match):
		return blueAlliance(match)
	if redWins(match):
		return redAlliance(match)
	else:
		return ()

def losingAlliance(match):
	if blueWins(match):
		return redAlliance(match)
	if redWins(match):
		return blueAlliance(match)
	else:
		return ()

def won(team):
	return lambda match: int(team)in winningAlliance(match)

def lost(team):
	return lambda match: int(team)in losingAlliance(match)

def isElim(match):
	return "Description" in match.keys()

def isFinal(match):
	return (match['Description'].find("Final") >= 0)

def isSemi(match):
	return (match['Description'].find("Semi") >= 0)

def isQtr(match):
	return (match['Description'].find("Qtr") >= 0)


FILTERS = {
"hasMoreWins":hasMoreWins,
"hasLessWins":hasLessWins,
"hasLosses":hasLosses,
"hasMoreLosses":hasMoreLosses,
"hasLessLosses":hasLessLosses,
"hasLosses":hasLosses,
"aboveRank":aboveRank,
"belowRank":belowRank,
"isRank":isRank,
"aboveQS":aboveQS,
"belowQS":belowQS,
"isQS":isQS,
"aboveRS":aboveRS,
"belowRS":belowRS,
"aboveMP":aboveMP,
"belowMP":belowMP,
"playedAtLeast":playedAtLeast,
"playedAtMost":playedAtMost,
"playedMatches":playedMatches,
"isTeam":isTeam,
"redWins":redWins,
"blueWins":blueWins,
"tie":tie,
"redAlliance":redAlliance,
"blueAlliance":blueAlliance,
"teams":teams,
"played":played,
"isRed":isRed,
"isBlue":isBlue,
"completed":completed,
"winningAlliance":winningAlliance,
"losingAlliance":losingAlliance,
"won":won,
"lost":lost,
"isElim":isElim,
"isFinal":isFinal,
"isSemi":isSemi,
"isQtr":isQtr
}

def generateFilter(arg):
	parts = arg.split("-")
	return FILTERS[parts[0]](*(parts[1:]))

def parseFilters(filters):
	fList = []
	for fset in filters:
		fSetList = []
		fset = re.sub("[\(\)]","",fset)
		for f in fset.split(","):
			fSetList.append(generateFilter(f))
		fList.append(filterByAll(fSetList))
	return fList
		
	pass		

def generateSort(arg):
	return re.sub("[\(\)]","",arg).split(",")
	pass